//MouseDevice.java
//John Hopf (Summer, 2002)

//Merged Itchy/Scratchy code - Benjamin Avery
//19 August 2003

import javax.comm.*;

import tracker.TrackerFastrak;
import tracker.TrackerIsotrakII;
import tracker.TrackerPolhemus;

import java.awt.Component;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.*;

public abstract class ButtonDevice {

	public static final int FORWARD_BUTTON = 1;
	public static final int BACKWARD_BUTTON = 4;
	public static final int STRAFE_LEFT_BUTTON = 5;
	public static final int STRAFE_RIGHT_BUTTON = 3;
	public static final int ROTATE_LEFT = 11;
	public static final int ROTATE_RIGHT = 10;
	
	
	/** a factory method that returns an instance of a mouse device 
	 *  for a given tracker. This is the preferred way to retrieve 
	 *  a mouse device.  */
	public static ButtonDevice getMouseDeviceForTracker(TrackerPolhemus tracker){
		if (tracker instanceof TrackerIsotrakII)
			return new ScratchyDevice(tracker);
		else if (tracker instanceof TrackerFastrak)
			return new ItchyDevice(tracker);
		return null;
	}
	
	public static ButtonDevice getKeyboardDeviceForAWTComponent(Component c){
		return new KeyboardDevice(c);
	}
	
	public abstract boolean getButton(int button);
	
}


class KeyboardDevice extends ButtonDevice implements KeyListener {
	
	private boolean keystate[] = {
			false, /* up key */
			false, /* spacebar */
			false, /* c */
			false, /* down key */
			false, /* z */
			false, 
			false, 
			false, 
			false, 
			false,
			false, /* keyboard control, left-key */
			false /* keyboard control, right-key */
	};
	
	public KeyboardDevice(Component keySource){
		keySource.addKeyListener(this);
	}
	
	/** mappings between hardware and software buttons are different
	 * on the two machines, so we need methods to handle each case.
	 */
	public boolean getButton(int button){		
		return keystate[button - 1];
	}

	public int idxForKey(KeyEvent e){
		switch (e.getKeyCode()){
		case KeyEvent.VK_UP:
			return FORWARD_BUTTON - 1;
		case KeyEvent.VK_DOWN:
			return BACKWARD_BUTTON - 1;
		case KeyEvent.VK_SPACE:
			return 1;
		case KeyEvent.VK_C:
			return STRAFE_LEFT_BUTTON - 1;
		case KeyEvent.VK_Z:
			return STRAFE_RIGHT_BUTTON - 1;
		case KeyEvent.VK_LEFT:
			return 10;
		case KeyEvent.VK_RIGHT:
			return 11;
		}
		return -1;
	}
	
	public void keyPressed(KeyEvent e) { 
		int idx = idxForKey(e);
		if (idx != -1)
			keystate[idx] = true;
	}

	public void keyReleased(KeyEvent e) {
		int idx = idxForKey(e);
		if (idx != -1)
			keystate[idx] = false;
	}

	public void keyTyped(KeyEvent e) {
	}	
}


abstract class TrackerButtonDevice extends ButtonDevice {
	
	private static CommPortIdentifier portId;
	
	private static Enumeration portList;
	
	private static final String COMPORT_NAME = "COM2";
	
	protected static ButtonDeviceSerialPort reader;
	
	
	protected TrackerButtonDevice(TrackerPolhemus tracker) {

		/*If keyboard mode enabled we don't use the mouse device */
		portList = CommPortIdentifier.getPortIdentifiers();
		while (portList.hasMoreElements()) {
			portId = (CommPortIdentifier) portList.nextElement();
			if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL)
				if (portId.getName().equals(COMPORT_NAME))
					reader = new ButtonDeviceSerialPort(portId);
		}
	}
}


class ScratchyDevice extends TrackerButtonDevice {
	
	public ScratchyDevice(TrackerPolhemus tracker){
		super(tracker);
	}
	
	/** mappings between hardware and software buttons are different
	 * on the two machines, so we need methods to handle each case.
	 */
	public boolean getButton(int button){		
		switch (button){
		case 1:
			return (reader.getButton7());
		case 2:
			return (reader.getButton8());
		case 3:
			return (reader.getButton5());
		case 4:
			return (reader.getButton6());
		case 5:
			return (reader.getButton4());
		case 6:
			return (reader.getButton1());
		case 7:
			return (reader.getButton2());
		case 8:
			return (reader.getButton3());
		case 9:
			return (reader.getButton9());
		case 10:
			return (reader.getButton10());
		default:
			return false;
		}
	}	
}


class ItchyDevice extends TrackerButtonDevice {
	
	public ItchyDevice(TrackerPolhemus tracker){
		super(tracker);
	}
	
	/** mappings between hardware and software buttons are different
	 * on the two machines, so we need methods to handle each case.
	 */
	public boolean getButton(int button){		
		switch (button){
		case 1:
			return (reader.getButton1());
		case 2:
			return (reader.getButton4());
		case 3:
			return (reader.getButton3());
		case 4:
			return (reader.getButton2());
		case 5:
			return (reader.getButton5());
		case 6:
			return (reader.getButton6());
		case 7:
			return (reader.getButton8());
		case 8:
			return (reader.getButton7());
		case 9:
			return (reader.getButton9());
		case 10:
			return (reader.getButton10());
		default:
			return false;
		}		
	}
}